Ce projet a été realisé par le groupe DataDigger :
De nos jours, avec la mécanisation de tous les secteurs de l'économie et surtout de la modernisation de plus en plus poussée du trafic routier, nous assistons à une augmentation exponentielle du nombre d'accidents de la route. Cette hécatombe et cette somme de souffrances, qui frappent tout particulièrement les jeunes n'épargnent aucun pays. Un patrimoine humain considérable se trouve ainsi anéanti, entraînant avec lui de très lourdes conséquences sociales et économiques. Si les actuelles statistiques sont déjà alarmantes, les tendances le seront encore plus.Les accidents de la circulation seront alors l'une des principales causes de morbidité dans le monde. Ce fardeau pèse plus lourdement sur les pays à faible revenu et les pays à revenu intermédiaire . Mieux connaître ce problème et ses multiples déterminants, en identifier les acteurs, nombreux et dispersés, en comprendre le contexte et les enjeux, chasser quelques idées reçues comme« les accidents interviennent surtout quand le trafic est dense, quelques km/h de plus, ce n'est pas bien dangereux... » Grâce à la contribution d'auteurs d'horizons variés, nous essayerons de croiser les regards, de générer des idées, afin d'améliorer la politique de prévention des accidents de la circulation dans ces deux pays.
Dans ce projet notre objective c'est de :
Notre objective DataScience est de :
Dans ce projet nous aurons recourt a la methode CRISP
Dans ce projet nous avons travaillé sur les Dataset suivants :
import pandas as pd
import sql
from pyspark import SparkContext
from pyspark.sql import SQLContext
Data=pd.read_csv(r'C:\Users\pc\AllDataFrames.csv',encoding='utf-8-sig')
Data.head(6)
Dans un premier temps on a voulu avoir le nom de la commune pour chaque département donnée on a donc travailler sur un jeu de donnée récupéré depuis le site afin de pouvoir avoir le nom de chaque commune et le code INSEE . Source : https://public.opendatasoft.com/explore/dataset/correspondance-code-insee-code-postal/table/?fbclid=IwAR2tPVM81qBlCS5nH5Z2zsQVclhFq23WY3he_fJcHMkGFbJxWVbONuXFsZA
import numpy
Data = Data.replace('', numpy.NaN)
dep1 = [numpy.NaN,'-','0']
com1 = [numpy.NaN,0]
dep2 = ['10','20','30','40','50','60','70','80','90','4']
newData = Data[~Data.dep.isin(dep1)]
newData = newData[~newData.com.isin(com1)]
newData = newData.dropna(subset = ['com'])
newData.com = newData.com.apply(lambda x: str(x)[0:-2])
newData.com = newData.com.apply(lambda x: '00'+x if len(x)==1 else x)
newData.com = newData.com.apply(lambda x: '0'+x if len(x)==2 else x)
newData.dep = newData.dep.apply(lambda x: '0'+x[0] if x in dep2 else x)
newData.dep = newData.dep.apply(lambda x: str(x)[0:-1] if str(x)[-1]=='0' else x)
newData.dep = newData.dep.apply(lambda x: str(x).replace('201','2A'))
newData.dep = newData.dep.apply(lambda x: str(x).replace('202','2B'))
newData['dep_com']=newData.dep + newData.com
On a ensuite fait la jointure entre le code INSEE et dep_com pour avoir la dataset suivante :
final=pd.read_csv(r'C:\Users\pc\Documents\final3.csv',sep=";")
final.head(10)
list(final.columns)
on peut remarquer la présence des variables dupliqué on va donc les supprimers
final=final.drop(['Unnamed: 0','X','Unnamed..0','Num_Acc..17','Num_Acc..35','Num_Acc..47','num_veh..55'],1)
final.head()
On va remplacer ensuite les variables manquantes avec la methode random
from scipy import stats
import random
while final.isna().any().any()==True:
for i in final.columns:
final[i] = final[i].fillna(random.choice(final[i]))
Nous allons ensuite regrouper les données par commune dans chaque année : on va commencer par rendre les variables muettes pour arriver a faire la somme des variables .
def OHE(df):
#col = df.select_dtypes(include=['category']).columns
col = ['lum','atm','col','agg','catr','circ','prof','plan','situ','obs','obsm','catu','grav','sexe','trajet','secu','actp','etatp']
print('Categorical columns in dataset',col)
c2,c3 = [],{}
for c in col:
if df[c].nunique()>2 :
c2.append(c)
c3[c] = 'ohe_'+c
df = pd.get_dummies(df,columns=c2,drop_first=True,prefix=c3)
print(df.shape)
return df
DummiedData=OHE(final)
DummiedData.columns
DummiedData.to_csv('DumiedData20052017.csv',index = False,sep=';')
sc =SparkContext.getOrCreate()
sql_ctx = SQLContext(sc)
df = sql_ctx.read.format('com.databricks.spark.csv').options(delimiter=';',header='true').load('DumiedData20052017.csv')
df.registerTempTable("DataSQL")
results = sql_ctx.sql("SELECT NomCommune, an, count(*) as nb_acc_tot ,sum(ohe_lum_2) as nb_acc_lum2 ,sum(ohe_lum_3) as nb_acc_lum3,sum(ohe_lum_4) as nb_acc_lum4,sum(ohe_lum_5) as nb_acc_lum5,sum(`ohe_catr_2.0`) as nb_acc_catr2,sum(`ohe_catr_3.0`) as nb_acc_catr3,sum(`ohe_catr_4.0`) as nb_acc_catr4,sum(`ohe_catr_5.0`) as nb_acc_catr5,sum(`ohe_catr_6.0`) as nb_acc_catr6,sum(`ohe_catr_9.0`) as nb_acc_catr9,sum(ohe_catu_2) as nb_acc_catu2,sum(ohe_catu_3) as nb_acc_catu3,sum(ohe_catu_4) as nb_acc_catu4,sum(`ohe_atm_2.0`) as nb_acc_atm2,sum(`ohe_atm_3.0`) as nb_acc_atm3,sum(`ohe_atm_4.0`) as nb_acc_atm4,sum(`ohe_atm_5.0`) as nb_acc_atm5,sum(`ohe_atm_6.0`) as nb_acc_atm6,sum(`ohe_atm_7.0`) as nb_acc_atm7,sum(`ohe_atm_8.0`) as nb_acc_atm8,sum(`ohe_atm_9.0`) as nb_acc_atm9,sum(`ohe_prof_1.0`) as nb_acc_prof1,sum(`ohe_prof_2.0`) as nb_acc_prof2,sum(`ohe_prof_3.0`) as nb_acc_prof3,sum(`ohe_prof_4.0`) as nb_acc_prof4,sum(ohe_grav_2) as nb_acc_grav2,sum(ohe_grav_3) as nb_acc_grav3,sum(ohe_grav_4) as nb_acc_grav4 FROM DataSQL GROUP BY NomCommune,an")
results.toPandas().to_csv('Aggregation.csv')
dataf =pd.read_csv('Aggregation.csv')
dataf.head(10)
from IPython.core.display import display, HTML
display(HTML('<iframe width="800" height="600" src="https://app.powerbi.com/view?r=eyJrIjoiZWVlMGQxZWMtNTVjNi00Y2I1LTljODktMzQ5MTBhZjllZWRkIiwidCI6ImYwNjA4MDQxLTU1ZGMtNDJjNS1iY2FkLTUzNjIzZTFhY2FlNCIsImMiOjh9" frameborder="0" allowFullScreen="true"></iframe>'))
D'apres la visualisation des data on peut voir que
data = pd.read_csv("Aggregation(1).csv")
data_orgin = data
pd.set_option('display.max_columns', 500)
data = data.drop('Unnamed: 0', axis=1)
data.head()
garv_score= data.nb_acc_grav2*100+data.nb_acc_grav4*10.8+data.nb_acc_grav4*0.44
data['Grav_Score'] = garv_score
data.head()
data.head()
%pylab inline
import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import seaborn as sns
sns.set()
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.stattools import acf, pacf
from copy import deepcopy
from datetime import datetime
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.graph_objs as go
init_notebook_mode(connected=True)
ci dessu un set de nombreux fonction importante dont on aura recourt dans la premiere partie .
# Functions :
"""Plots a simple serie in PLOTLY."""
def jsplot(dates , values , mode = 'lines+markers'):
data = [go.Scatter(
x=dates,
y=values,
mode = mode)]
iplot(data)
"""Plot multiple series in PLOTLY:"""
def jsplot_multiple(dates , values , mode = 'lines+markers'):
data = []
for col in values.columns:
splot = go.Scatter(
x=dates,
y=values[col],
mode = mode,
name = str(col) )
data.append(splot)
iplot(data)
"""Function that test the stationarity of a Time series by
computing and plotting rolling statistics, and then by performing
An augmented Dickey Fuller test."""
def test_stationarity(timeseries , window = 50):
#Determing rolling statistics
rolmean = timeseries.rolling(window).mean()
rolstd = timeseries.rolling(window).std()
#Plot rolling statistics:
fig = plt.figure(figsize=(12, 8))
orig = plt.plot(timeseries,label='Original')
mean = plt.plot(rolmean, color='red' , label='Rolling Mean')
std = plt.plot(rolstd, label = 'Rolling Std')
plt.legend(loc='best')
plt.title('Rolling Mean & Standard Deviation')
plt.show()
#Perform Dickey-Fuller test:
print('Results of Dickey-Fuller Test:')
try:
dftest = adfuller(timeseries.dropna(), autolag='AIC')
dfoutput = pd.Series(dftest[0:4], index=['Test Statistic','p-value','#Lags Used','Number of Observations Used'])
for key,value in dftest[4].items():
dfoutput['Critical Value (%s)'%key] = value
print(dfoutput)
except:
print('test failed')
"""Performs Acp - Pacp Analysis on a time serie."""
def acp_pacp(timeseries , nlags = 30):
lag_acf = acf(timeseries, nlags=nlags)
lag_pacf = pacf(timeseries, nlags=nlags, method='ols')
print('lag_acf')
fig = plt.figure(figsize=(7 , 6))
sns.barplot( np.arange(len(lag_acf)) , lag_acf , palette = 'GnBu_d')
plt.axhline(y=0,linestyle='--',color='gray')
plt.axhline(y=-1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
plt.axhline(y=1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
plt.show()
print('lag_pacf')
fig = plt.figure(figsize=(7, 6))
sns.barplot( np.arange(len(lag_pacf)) , lag_pacf , palette = 'GnBu_d')
plt.axhline(y=0,linestyle='--',color='gray')
plt.axhline(y=-1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
plt.axhline(y=1.96/np.sqrt(len(timeseries)),linestyle='--',color='gray')
plt.show()
caracs = pd.read_csv('caracteristics.csv' , encoding = 'latin-1') # Caracteristics of the accidents.
places = pd.read_csv('places.csv' ) # Places features.
users = pd.read_csv('users.csv' ) # Users involved in the accdient features.
vehicles = pd.read_csv('vehicles.csv') # Vehicles features.
caracs2017 = pd.read_csv('caracteristiques-2017.csv' , encoding = 'latin-1') # Caracteristics of the accidents.
on importe aussi tout les étés en france entre 2005 et 2017. ces informations sont valorisantes vue qu'elles affectes toujours le traffic et le comportement des conducteurs
holidays = pd.read_csv('holidays.csv') # Vehicles features.
holidays.head()
caracs = pd.concat([caracs2017,caracs])
caracs.head()
places.head()
On construit la serie tomporelle en comptant les nombres des accident par jour en paris entre 2005 et 2017. et apres on visualise le resultat dans plotly .
dtsers = caracs.loc[(caracs.dep.isin([750])) , ['Num_Acc' , 'jour' , 'mois' , 'an']]
# zedna colom day feha feha y/m/d w dropina jour mois an
dtsers['day'] = pd.to_datetime((2000+dtsers.an)*10000+dtsers.mois*100+dtsers.jour,format='%Y%m%d')
dtsers.drop(['jour' , 'mois' , 'an'] , axis = 1 ,inplace = True)
dtsers = dtsers.groupby('day' , as_index = False).count()
# Dummy Variable Holiday
dtsers['isholiday'] = 0
dtsers.loc[dtsers.day.isin(holidays.ds) , 'isholiday'] = 1
# Week day and month
dtsers['weekday'] = dtsers.day.dt.weekday
dtsers['month'] = dtsers.day.dt.month
# Dummification
dtsers = pd.get_dummies(dtsers , columns = ['weekday' , 'month'])
print(' the 3 last years of the time series:')
#dtsers.day[3500] bech traj3ek li 2014 08 02 w bech tarja3 b number daccdent li nfes el wa9t
jsplot(dtsers.day[3500:] , dtsers.Num_Acc[3500:] )
z=dtsers.head()
dtsers.head()
z.to_csv('out.csv')
Les séries Temporelles sont stationnaires si elles n’ont pas d’effet de tendance ou de saisonnalité.
Il ne semble pas y avoir de tendance particulière dans la série Temporelle. Mais nous pouvons noter des modèles saisonniers qui seront d'une grande valeur pour notre modèle, ainsi qu'un grand nombre de pics que nous pouvons essayer d'expliquer pour mieux comprendre le problème. Voyons cela de plus près.
Commençons par calculer certaines statistiques telles que la moyenne et l'écart-type glissants, et utilisons un test statistique (Dickey-Fuler) pour déterminer si la série est stationnaire.
La stationnarité d'une série Temporelle est importante pour la modélisation. Certains modèles ne peuvent fonctionner qu'avec des séries temporelles stationnaires. C'est également un bon aperçu de la structure de la série chronologique: cette analyse nous aide à détecter les tendances, les ruptures structurelles et tout type de configuration anormale qui peut nous aider à mieux comprendre et à adapter nos modèles et à les généraliser davantage.
nous testons la saritéarité autour de la moyenne et de la variance
# Statistique :
test_stationarity(dtsers.Num_Acc , window = 30)
The p-value of the test indicates that the series is stationary. We don't notice any significant trend, but we can clearly see seasonal patterns.
Let's now look at the auto correlation plots:
la p-value des teste démontre que la serie est stationnaire .Nous ne remarquons aucune tendance significative, mais nous pouvons clairement voir les tendances saisonnières.
acp_pacp(dtsers.Num_Acc) # Nombre d'accident par jour
Ces graphiques confirment qu'il existe une forte saisonnalité dans nos données. Nous pouvons clairement voir que nous avons ici une saisonnalité hebdomadaire, donc une tendance qui se répète chaque semaine. Ce type de modèle est précieux car il nous permettra d’améliorer nos prévisions en fonction de ce qui s’est passé la semaine dernière, par exemple. Nous pouvons également noter une forte corrélation avec ce qui s'est passé la veille.
Suivons plus de types de saisonnalité:
Saisonnalité horaire
Ce type de saisonnalité ne sera d'aucune utilité pour notre modèle, mais il est bon de savoir si nous voulons construire un modèle horaire plutôt qu'un modèle quotidien. Nous additionnerons simplement le nombre d'accidents par heure après avoir distingué les accidents graves (mort ou blessures graves) du reste et verrons ce que nous pouvons trouver:
tempas = caracs.loc[caracs.dep == 750 , ['Num_Acc' , 'hrmn']]
tempas['hour'] = tempas['hrmn'].apply(lambda x:str(x).zfill(4)[:2])
grave_accs = users[users.grav.isin([2,3]) ].Num_Acc
tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1
# bech ta3mel dataset feha el wa9t w el somme ta3 el gravity
# (5thina ken acc 2 w acc 3 w7tina ken moucch grav =0 w ken grave = 1 w3malana par rapport ombre total des acc)
occs = tempas.drop('hrmn' , axis = 1).groupby('hour' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})
trace1 = go.Area(
r=list(occs.Num_Acc),
t=list(occs.hour),
name='Total Number of accidents',
marker=dict(
color='rgb(155, 236, 0)'
)
)
trace2 = go.Area(
r=list(occs.gravity),
t=list(occs.hour),
name='Grave accidents',
marker=dict(
color='rgb(158,154,200)'
)
)
data = [trace1 , trace2]
layout = go.Layout(
title='Repartition of accidents per Hour',
autosize = False,
width = 1000,
height = 500,
orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
Nous pouvons clairement remarquer deux pointes, une à 09h00, le moment où les gens se rendent au travail, et une autre entre 17h00 et 18h00, au moment où les gens rentrent chez eux. Le nombre d'accidents diminue entre ces deux pics. Rien d'inhabituel, mais cela prouve qu'il existe une tendance.
Nous pouvons également constater qu’il ya peu d’accidents graves à Paris car il n’ya que des routes de ville.
Saisonnalité journalière
tempas = caracs.loc[caracs.dep == 750 ,['Num_Acc']]
tempas['date'] = pd.to_datetime((2000+caracs.an)*10000+caracs.mois*100+caracs.jour,format='%Y%m%d')
tempas['weekday'] = tempas['date'].dt.weekday.apply(lambda x:str(x).zfill(2))
tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1
occs = tempas.drop('date' , axis = 1).groupby('weekday' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})
trace1 = go.Area(
r=list(occs.Num_Acc),
t=list(occs.weekday),
name='Total Number of accidents',
marker=dict(
color='rgb(106,81,163)'
)
)
trace2 = go.Area(
r=list(occs.gravity),
t=list(occs.weekday),
name='Grave accidents',
marker=dict(
color='rgb(158,154,200)'
)
)
data = [trace1 , trace2]
layout = go.Layout(
title='Repartition of accidents per weekday',
autosize = False,
width = 1000,
height = 500,
orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
occs
Même chose ici, nous pouvons clairement remarquer une tendance, où le nombre d'accidents diminue le vendredi et le dimanche et atteint son minimum le samedi. Les autres jours sont à peu près les mêmes (jours ouvrables).
Saisonnalité mensuelle
tempas = caracs.loc[caracs.dep == 750 ,['Num_Acc' , 'mois']]
tempas['mois'] = tempas['mois'].apply(lambda x:str(x).zfill(2))
tempas['gravity'] = 0
tempas.loc[tempas.Num_Acc.isin(grave_accs),'gravity'] = 1
occs = tempas.groupby('mois' , as_index = False).agg({'Num_Acc' : 'count' , 'gravity' : 'sum'})
trace1 = go.Area(
r=list(occs.Num_Acc),
t=list(occs.mois),
name='Total Number of accidents',
marker=dict(
color='rgb(106,81,163)'
)
)
trace2 = go.Area(
r=list(occs.gravity),
t=list(occs.mois),
name='Grave accidents',
marker=dict(
color='rgb(158,154,200)'
)
)
data = [trace1 , trace2]
layout = go.Layout(
title='Repartition of accidents per Hour',
autosize = False,
width = 1000,
height = 500,
orientation=-90
)
fig = go.Figure(data=data, layout=layout)
iplot(fig)
occs
Encore une fois, on peut voir un motif annuel dans la série chronologique, fortement lié au temps passé en vacances (août, décembre, ...).
En incorporant ces modèles dans nos modèles, nous pourrons faire de meilleures prévisions.
Pour noter nos modèles, nous allons utiliser cette fonction qui calcule un ensemble de statistiques significatives pour les prédictions que nous faisons. Nous allons tester notre modèle l'année dernière et voir comment il fonctionne.
La fonction ci-dessous calculera l'erreur moyenne, l'erreur absolue moyenne (MAE), l'erreur quadratique moyenne (RMSE), l'erreur moyenne en pourcentage (MPE), la corrélation entre la valeur vraie et l'erreur pour voir s'il reste des informations. . Il va également tracer la distribution de l'erreur et la prédiction par rapport à la valeur vraie en fonction du temps.
def evaluate(y_true , y_pred , dates):
try:
true_value , prediction = y_true.sum(axis = 1), y_pred.sum(axis=1).round()
except:
true_value , prediction = y_true, y_pred.round()
print('Mean Absolute Error :' , round(abs(true_value - prediction).mean() , 2))
print('Root Mean Square Error:' , round(sqrt(((true_value - prediction)**2).mean()) , 2) )
print('Mean Percentage Error :' , round((abs(true_value - prediction)/true_value).mean() , 2) )
error = pd.Series(true_value - prediction)
#density plot :
print('Error Density :')
error.plot.density()
plt.show()
# mean of error and correlation :
print('Mean Error :' , round(mean(error) , 2 ))
print('True Value And error Correlation :' , round(np.corrcoef(error , true_value)[0 , 1] , 2))
# plot :
to_plot = pd.DataFrame({'target' : y_true.reshape(-1) , 'prediction' : y_pred.reshape(-1)})
jsplot_multiple(dates , to_plot)
Avant d'aller plus loin, nous devons créer un modèle «naïf» qui représentera la performance minimale acceptable pour pouvoir comparer les modèles que nous allons construire. Ce modèle doit être le plus simple et le plus intuitif possible.
Puisque nous avons de fortes tendances saisonnières et aucune tendance, nous prendrons le nombre d'accidents l'année dernière dans la même journée la même semaine que la prévision pour cette année et verrons quelles performances nous obtiendrons:
on utilise 2015 pour predire 2016 :
# Naive Model :
new , old = (dtsers.loc[dtsers.day.dt.year == 2016 , ['day' , 'Num_Acc']].reset_index(drop = True) ,
dtsers.loc[dtsers.day.dt.year == 2015 , ['day' , 'Num_Acc']].reset_index(drop = True)[:365])
old.columns = ['day' , 'old']
new['weekofyear'] , new['dayofweek'] = new.day.dt.weekofyear , new.day.dt.dayofweek
old['weekofyear'] , old['dayofweek'] = old.day.dt.weekofyear , old.day.dt.dayofweek
merged = new.merge(old , on = ['weekofyear' , 'dayofweek'])
evaluate(merged.Num_Acc.values , merged.old.values , dtsers.day[-365:])
2016-2017 :
# Naive Model :
new , old = (dtsers.loc[dtsers.day.dt.year == 2017 , ['day' , 'Num_Acc']].reset_index(drop = True) ,
dtsers.loc[dtsers.day.dt.year == 2016 , ['day' , 'Num_Acc']].reset_index(drop = True)[:365])
old.columns = ['day' , 'old']
new['weekofyear'] , new['dayofweek'] = new.day.dt.weekofyear , new.day.dt.dayofweek
old['weekofyear'] , old['dayofweek'] = old.day.dt.weekofyear , old.day.dt.dayofweek
merged = new.merge(old , on = ['weekofyear' , 'dayofweek'])
evaluate(merged.Num_Acc.values , merged.old.values , dtsers.day[-356:])
Nous allons d'abord essayer la bibliothèque Prophet, créée par Facebook. Prophet est un outil de prévision développé par Facebook pour sa planification de la capacité. Il est très efficace lorsqu'il s'agit de problèmes à taille humaine. Il est basé sur des modèles additifs généralisés.
La bibliothèque elle-même est facilement utilisable, car le modèle se paramétrera lui-même pour la plupart. Il prend également directement les dates brutes et les vacances sans qu'il soit nécessaire de prétraiter ces variables.
Essayons ce modèle sur nos données.
from fbprophet import Prophet
#Initialisation of the model.
model = Prophet(holidays = holidays , yearly_seasonality=True , weekly_seasonality=True, daily_seasonality=False)
#train & test set.
histo , new = dtsers[dtsers.day.dt.year < 2016].reset_index(drop = True) , dtsers[dtsers.day.dt.year
== 2016].reset_index(drop = True)
# We rename the columns before fitting the model to Prophet.
ncols = histo.columns.values
ncols[0] , ncols[1] = 'ds' , 'y'
histo.columns , new.columns = ncols , ncols
# We fit the model.
model.fit(histo)
# Prediction
ypred = model.predict(new)['yhat'].round()
# Evaluation
evaluate(new.y.values , ypred.values , dtsers.day[-365:])
Nous pouvons constater une nette amélioration par rapport au modèle naïf. nous avons pu réduire l'erreur moyenne en pourcentage de 7% et nous avons également amélioré les autres mesures (de 38% à 29%)
# import the required libraries
from plotly.offline import init_notebook_mode, iplot
import plotly.graph_objs as go
import numpy as np
import plotly.plotly as py
from plotly import tools
import pandas as pd
import string, os, random
import calendar
import numpy as np
globalcolors = ['092a35', 'a2738c', '645c84', '427996', '658525', '404b69', '0f4471', '0f4471', '0f4471', '0f4471']
init_notebook_mode(connected=True)
punc = string.punctuation
df1 = pd.read_csv('caracteristics.csv', low_memory = False, encoding = 'latin-1')
df2 = pd.read_csv('vehicles.csv', low_memory = False)
df3 = pd.read_csv('places.csv', low_memory = False)
df4 = pd.read_csv('users.csv', low_memory = False)
from functools import reduce
accidents = reduce(lambda left, right: pd.merge(left, right, on = "Num_Acc"), [df1, df2, df3, df4])
accidents = accidents.drop(['v2', 'v1', 'long', 'lat', 'pr1', 'pr', 'gps'], axis = 1)
accidents.columns.values
accidents.an += 2000
dates = pd.to_datetime(accidents.an*10000+accidents.mois*100+accidents.jour,format='%Y%m%d')
accidents.an -= 2000
traces = []
for key, grp in dates.groupby(dates.dt.year):
#print(grp)
aggregated = grp.dt.month.value_counts().sort_index()
x_values = aggregated.index.tolist()
y_values = aggregated.values.tolist()
x1,y1 = x_values, y_values
x1 = [calendar.month_name[int(x)] for x in (x1)]
#x1, y1 = create_stack_bar_data('jour', accidents)
trace1 = go.Scatter(x=x1, y=y1, opacity=0.75, line = dict(
width = 1.5), name = str(key), marker = dict(color = np.random.randn(500)*key), mode = 'lines',
text = str(key))
layout = dict(height=400, title='Time Series of Accidents for each Year', legend=dict(orientation="h"));
traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig, filename='stacked-bar')
Conclusion :
Exploration basée sur les routes où des accidents sont survenus
# function to aggregate and return keys and values
def create_stack_bar_data(col, df):
aggregated = df[col].value_counts().sort_index()
x_values = aggregated.index.tolist()
y_values = aggregated.values.tolist()
return x_values, y_values
x1, y1 = create_stack_bar_data('an', accidents)
for i in range(len(x1)):
x1[i] += 2000
x1, y1 = create_stack_bar_data('catr', accidents)
x1 = ['Highway', 'National Road', 'Departmental Road', 'Communal Way', 'Off-Public Network', 'Parking Lot', 'Other']
trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name="Category")
x2, y2 = create_stack_bar_data('circ', accidents)
x2 = ['Unknown','One Way', 'Bidirectional', 'Separated Carriageways', 'Variable Assignment Channels']
trace2 = go.Bar(x = x2, y = y2, opacity = 0.75, name = "Traffic Flow")
x3, y3 = create_stack_bar_data('prof', accidents)
x3 = ['Unknown', 'Dish','Slope', 'Hill-Top', 'Hill-Bottom']
trace3 = go.Bar(x = x3, y = y3, opacity = 0.75, name = "Road Gradient")
fig = tools.make_subplots(rows = 3, cols = 1)
fig.append_trace(trace1, 1, 1)
fig.append_trace(trace2, 2, 1)
fig.append_trace(trace3, 3, 1)
layout = dict(height=900, title='Accidents by Type of Road');
fig.layout.update(layout)
#fig['layout'].update(height=800,title='Accidents by Type of Road')
iplot(fig, filename='stacked-bar')
keydict = {1:'Highway', 2:'National Road', 3:'Departmental Road', 4:'Communal Way', 5:'Off-Public Network', 6:'Parking Lot', 9:'Other'}
roadtype = accidents[['catr','circ']]
traces = []
for key, grp in roadtype.groupby(roadtype.catr):
aggregated = grp.circ.value_counts().sort_index()
x_values = aggregated.index.tolist()
y_values = aggregated.values.tolist()
x1,y1 = x_values, y_values
x1 = ['Unknown','One Way', 'Bidirectional', 'Separated Carriageways', 'Variable Assignment Channels']
#x1, y1 = create_stack_bar_data('jour', accidents)
trace1 = go.Bar(x=x1, y=y1, opacity=0.75, name = keydict[key])
layout = dict(height=400, title='Distribution of Accidents based on Type of Road', legend=dict(orientation="h"));
traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig)
Répartition des personnes impliquées dans des accidents par âge
ageusers = accidents[['an_nais', 'catu']]
ageusers['age'] = 2016 - ageusers.an_nais
keydict = {1:'Driver', 2:'Passenger', 3:'Pedestrian', 4:'Pedestrian in Motion'}
traces = []
for key, grp in ageusers.groupby(ageusers.catu):
if(key < 4):
#aggregated = grp.an_nais.value_counts().sort_index()
x1 = grp.age.values
#y_values = aggregated.values.tolist()
#x1,y1 = x_values, y_values
#x1 = ['Driver','Passenger', 'Pedestrian', 'Pedestrian in Motion']
#x1, y1 = create_stack_bar_data('jour', accidents)
trace1 = go.Histogram(x=x1, opacity=0.5, name = keydict[key])
layout = dict(height=400, title='Distribution of People involved in Accidents by Age',
legend=dict(orientation="h"), barmode = 'overlay');
traces.append(trace1)
fig = go.Figure(data= traces, layout=layout)
iplot(fig)